'''
1、为什么学python？
      Ui自动化测试、接口自动化测试
2、python只是编程语言，需结合其他工具使用
   python + selenium web自动化（功能测试转换为代码）
   python + appium 移动端自动化（手机端App）
   python + request 接口自动化（手机端App）
3、编程语言的分类：
      编译型：将书写的代码转换为一个二元制文件，直接在硬件上执行，效率高 - C、C++、Swift、Obiect-C
      解释型：在代码执行时，将代码转换为二进制，实时解释，边执行变转换（解释），效率慢 - python、Javascript、Ruby、PHP
4、PEP8：代码的规范书写，不按照这个规范书写，会有灰色波浪线提示
    自动格式化：ctrl+alt+l
              或：
              菜单栏 - code -reformat code
5、设置快捷键：setting - keymap - 搜索相关功能，并修改快捷方式
6、波浪线：
     红色：代码错误，必须修改
     灰色：格式不标准，可修改
     绿色：提示不是一个单词，可修改
7、终端可以直接运行：python E:/project/learn-python/python入门/2-4 第二篇 面向对象（案例- 房子和家具添加）.py
   在E:/project/learn-python/python入门/test.py目录下，输入cmd，进入终端  - dir - python 2-4 第二篇 面向对象（案例- 房子和家具添加）.py
   pycharm的终端页面：python 2-4 第二篇 面向对象（案例- 房子和家具添加）.py
8、快速写：type(age).print -回车
         =print(type(age))
9、动态代码模板：
        ① 创建：
                file - settings - editor(live templates) - 右侧"+"  - live template：
                        Abbreviation： 名称
                        Descripti：    基本介绍（方便后期了解代码具体是什么内容）
                        template text：复制粘贴代码内容
                        define：       勾选 python
                点击Apply - 点击ok
        ② 使用：
                新建.py文件 - 输入动态模板名称 - 回车
        ③ 删除： file - settings - editor(live templates) - 选中 - 右侧"-"
10、快捷方式：
      11 导包：         选中 - alt + 回车
      12 美化json文件：  code - reformat code
      13 查看源代码：    按住ctrl，点击目标代码
      14 查看关键字：    print(help('keywords'))
      15 替换：         ctrl + r
      16 查看注释文档    view - quick documentation
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36


TODO 1  python 基础
变量、变量类型、输入输出、运算符
1、变量命名：字母数字下划线组合，不能数字开头
           严格区分大小写
2、类型转换：
     int()：float、整数类型的字符串
     float(): int、数字类型（整数、小数）的字符串
     str()：任何类型，一般直接加引号
3、格式化：
      %.2f：保留2位小数
      %06d：#000001，补5个零，共6位
      %d%%：#90%
         print(f"姓名：{name}，年龄：{age:.2f}，学号：{num:05d}")
         print("姓名：{name}，年龄：{:.2f}，学号：{:05d}".format(name. age, num))
4、快捷键：
    删除一行：ctr + x
    换行：shift + 回车
5、debug：调试代码，查找错误
     测试：查看代码执行步骤
     ① 打断点：一般在代码第一行，只有一个断点不能debug调试，可以在其他任意地方多加一个断点
     ② 右键 - debug运行代码
6、无限循环：用break终止
      while True:
          重复执行的代码
          if 判断条件：
             break
          重复执行的代码
    break、continue：只能在循环中使用
7、for循环：遍历的数据（str、list、tuple、dict）
8、range(n)：      [0,n)，循环n次
  range(1,3):     [1,3)
  randint(1,3):   [1,3]
  切片：           [1:5:1]   ---[1,5)
      截取2-5（包含）       [2: 6]
      截取2-末尾（包含）     [2: ]
      截取2-末尾（不包含）   [2: -1]
      截取末尾两个字符       [-2: ]
      逆转                 [: : -1]
9、find查找方法：
      str.find('and', start, end)
          start:默认0
          end：默认len()
          找到了，返回第一次出现and的整数下标
          找不到，返回-1
      str.index('and', start, end)    - 区别：找不到，直接报错
      str(i).find('7') != -1          - 将数字i转化为字符串，查找是否包含7，不等于-1，即找到了7
      = '7' in str(i)
  replace替换方法：
      str.replace(old, new, count)
          count：替换的次数，默认全部替换
  split拆分方法：
      str.split('and', maxsplit)
          and：默认空白字符（空格、/n、/t）
          maxsplit：拆分的次数，默认全部拆分
      按照空白拆分一次：str.split(maxsplit=1)
  join连接方法：
      str.join(列表)
         列表：主要是列表，可以是其他容器（字符串、元组、字典等）
         列表的数据使用逗号隔开，数据必须都是字符串
         ' '.join(list1)
         ‘_’.join('hello')
10、列表：
           list=list("hello")   --- list = ['h', 'e', 'l', 'l', 'o']
       index查找方法：返回下标值
           list.index('and', start, end)
       count统计方法：
           list.count('and')
       append尾部添加：
           list.append('and')
       insert插队添加：
           list.insert(2, 'and')  -原数据后移
       extend逐个添加：
           list.extend(list2)
       列表推导式：
           list = [for 'hello' in range(2)]   -- list = ['hello', 'hello']
       修改：
           list[0] = '张三'    - 返回删除的数据，数据不存在，会报错
       删除：
           list.pop(下标)      - 默认最后一个
           list.remove(数据值） - 返回None，数据不存在，会报错（只能删除第一个值）
           list.clear()       - 一般不用
       反转：
           list[::-1]         - 原列表不变，生成新列表
           list.reverse()     - 直接改变原列表，返回None
       复制：
           list1 = list[:]
           list1 = list.copy()
       排序：
           list.sort()                   - 升序
           list.sort(reverse = True)     - 降序
       去重：
           list(set(old_list))

           list = [2, 3, 42, 4, 6, 8, 4, 2, 57]
           new_list = []
           for i in list:
              if i in new_list:
                 pass/continue
              else:
                 new_list.append(i)
           print(new_list)
           或：
           for i in list:
               if i not in  new_list:
                   new_list.append(i)
       +=：对于列表而言，相当于extend
       组包（pack）：将多个数据值使用逗号连接的过程，组成元组
       拆包（unpack）：将容器中的数据值使用多个变量分别保存的过程，变量的个数和容器中的数据个数一致
11、元组：
       与列表的区别：
            元组数据不能改，列表可以修改
            元组-()， 列表-[]
       tuple=tuple("hello")   ---tuple = ('h', 'e', 'l', 'l', 'o')
       只有一个数据，其后必须加逗号
12、字典：
       增加、修改：
            dict['name'] = '张三'         - 存在，即修改；不存在，即新增
            dict['like'].append('学习')   - 字典中，值为列表的新增
       删除：
            del dict['name']
            dict.pop('name')
            dict['like'].pop(0)
            dict['like'].remove('烫头')
       清空：
            dict.clear()
       查询：
            dict['like']               - 没有，会报错
            dict.get('like')           - 没有，返回None
            dict.get('like', '保密')    - 没有，返回保密
       遍历：
            for key, value in dict.items():
            for key in dict.keys():
            =for key in dict:
            for key in dict.values():
13、容器总结：
       + ：      字符串、列表、元组支持加法
       * n：     字符串、列表、元组支持乘某个数
       len():   容器均可用
       in：     容器均可用（字典中，判断key是否存在）
14、函数：
       把具有独立功能的代码块组织成一个模块，在需要的时候调用
       函数体：def缩进的代码
       鼠标放到函数名，ctr + q   - 函数定义的详细信息
                    ctr + b   - 回到函数定义的位置
                    = 按住ctr，鼠标左键
       文档注释：函数名下方，三引号（给别人看）
       嵌套：一个函数中调用另一个函数
15、可变类型：列表、字典、集合
16、print():
      sep=''：多个位置参数之间的间隔
      end='\n'：打印之后的换行操作
17、函数参数：
       形参：函数定义时书写的参数
       实参：函数调用时书写的数据值
       缺省参数：函数定义时，直接给形参设置默认值（必须在普通参数后）
       传参：
          关键字传参必须在位置传参后
       不定长参数：
            不定长位置参数：  *args，元组
            不定长关键字参数：**kwargs，字典
       参数顺序：def fun(普通参数，*args，缺省参数，**kwargs)
18、交换两个变量的值：a, b = b, a
19、局部变量：函数内部定义，不同函数中可定义相同的局部变量
    全局变量：函数外定义，或使用global声明
            在函数内，想修改全局变量，必须先使用global声明
20、将列表（元组）中的数据,分别作为位置参数，需要对列表（元组）进行拆包操作
       sum(*list)   - sum 为求和函数
    将字典中的数据,分别作为关键字参数，需要对字典进行拆包操作
       sum(**dict)
21、匿名函数 - lambda：
       只能书写一行代码，其结果就是返回值
       返回值不需要return
       fun1 = lambda : print('hello word')
       fun1()
       参数为字典，返回键为age的值： fun = lambda x: x.get('age') = lambda x: x['age']
                                dict = {'name': 'xiaoming', 'age': 21}
                                print(fun(dict))
       列表中的字典排序：list.sort(key=lambda x: x['name'])                    或：         def get_value(x):
                     list.sort(key=lambda x: x['name'], reverse=True)                      return x['name']
                     print(list)                                                       list.sort(key=get_value)
22、字符串比大小：                                                                        print(list)
       A < Z < a < z
       ord(a)：      获取字符的-ASCII-值
       chr(ASCII值)：获取对应的字符
23、面向过程：关注具体步骤的实现，所有功能自己写，    亲历亲为， 定义一个函数，按照顺序调用函数
    面向对象：关注结果         谁（对象）帮我做事  偷懒      定义一个对象，让对象去做
       在程序代码中，对象是由类创建的
           类、对象是面向对象编程思想非常重要的两个概念
               类：  抽象概念，对多个特征和行为相似的事物统称
                    泛指多个
               对象：具体概念，具体存在的一个事物，看得见摸得着
                    特指一个
    类的组成：
       类名：首字母大写       - 人类-Person、People
       属性：有什么，名词     - 名字（name）、年龄（age）、身高（height）
       方法：做什么，动词     - 跑步（run）、吃（eat）
    步骤：
      定义类
      创建对象
      通过对象，调用方法
    代码：
       ① 定义类：
            class 类名:
               def 方法名(self):
                    pass
       ② 创建对象：
            变量 = 类名()     - 只要出现类名()，就创建一个对象
                              这个变量，即对象
       ③ 调用方法
            对象.方法名()
    self：
       cat 对象调用 eat 方法，解释器会将 cat 对象传给 self， self 的本质就是对象
          print(f"{id(self)}", self)
          print(f"{id(cat)}", cat)         - cat 和 self 的引用地址一样
    添加、获取属性：
       类内部：                       - 在__init__(self)方法中添加
          self.属性名 = 属性值
          self.属性名
       类外部                         - 一般不用
          对象.属性名 = 属性值
          对象.属性名
       快捷键： 光标放好，alt + 回车
    魔法方法：
       __ __格式，满足某个条件下，会自动调用
       __init__：
           什么时候自动调用：创建对象后
           怎么用：        给对象添加属性（初始化方法、构造方法）
                         每次创建对象后，都要执行的代码都可以写在__init__方法
                         不要在里面写 print()
       __str__:
           什么时候自动调用：使用print(对象)打印对象时
           怎么用：        查看信息
                         如果类中没有__str__，print(对象)，默认输出对象的引用地址
           注意：         必须返回一个字符串
           代码：  def __str__(self):                                      替换前：   def info(self):
                      return f"品种是{self.name}，年龄是{self.age}"                       print(f"品种是{self.name}，年龄是{self.age}")
                  print(cat)
       __del__:（析构方法）
           对象被删除销毁时，自动调用（遗言） - 基本不使用
           直接使用 del 对象，删除对象（如果对象有多个名字，即：多个对象引用一个变量，需要把所有的对象都删除才可以）
       dir(对象)：获取对象的所有方法
24、私有和公有：
       在python中，可以添加访问控制权限（公有权限、私有权限）
           公有：直接书写的方法和属性，可以任意地方访问和使用
           私有：在类内部，__某，为私有的，只能在当前类中使用
                什么时候定义私有：某个属性或方法，不想在类外部访问或使用，可定义为私有
                               测试中，一般使用公有，不定义私有
                               开发中，会根据需求文档，定义私有
                类外部操作私有属性：在类内部定义公有的方法，通过公有方法去操作私有属性
                本质：python解释器执行代码时，发现__某，会将其重命名，如：self.__age  -> self._Person__age       - Person  类名
                     类外部可以使用，print(person._Person__age)，但是不要用                                    person  对象
                                  person._Person__age = 17                                               __age   私有属性
       __dict__：魔法属性，可以将对象具有的属性组成字典返回
                 person.__age = 17          - 添加一个公有属性__age
                 print(person.__dict__)       将person对象的属性按照字典格式打印
25、面向对象的三大特性：
      ① 封装：在类中定义属性和方法（即：定义类的过程）
      ② 继承：实现代码的重用复用，描述的是类与类之间的关系，减少代码的冗余，可以直接使用
              代码：
                  class A:           等同于：         class A(object):
                  class B(A):
              A类：父类、基类，也有其父类 - object（python中最顶级/原始的类）
              B类：子类、派生类
             继承后，子类拥有父类所有的公有属性和方法，可以调用父类的父类中的方法
             单继承：一个类只继承一个父类
             案例：
                 class Animal:
                    def eat(self):
                         print("动物 - 吃")
                 class Dog(Animal):
                    def bark(self):
                         print("狗 - 叫")
                 class XTQ(Dog):
                    pass
                 xiao = XTQ()
                 xiao.eat()
                 xiao.bark()
             重写：在子类中重新定义和父类中名字相同的方法
                  ① 原因：父类中的方法不能满足子类的需求
                  ② 特点：调用子类自己的方法，不再调用父类的方法
                  ③ 方式：
                        覆盖：完全摒弃掉父类的功能，重写
                             名字相同，代码不同
                        扩展：在父类功能的基础上，添加新功能（使用较多）
                  ④ 代码：
                       class Dog:
                          def bark(self):
                              print("汪汪汪。。。")        - 父类中的功能（汪汪汪）
                       class XTQ(Dog):
                          def bark(self):               - 新功能（嗷嗷嗷)
                              print("嗷嗷嗷。。。")
                              super().bark()            - 调用父类的代码
                              print("嗷嗷嗷")
      ③ 多态：不同的对象，调用相同的方法，产生不同的执行结果，增加代码的灵活度
              一种调用技巧
26、实例对象：
       平时所说的对象，称为实例对象（实例）
       类的实例化：创建对象的过程
       每个实例对象，都有自己的空间，其中保存自己的属性（实例属性）
           实例属性：
              定义：在__init__中，使用 self.name = name
              使用：在方法中，使用 self.name 来获取（调用）
              内存：每个实例中都有一份
              例子：每只狗都有自己的名字，改变的话不会同时变，为实例属性
    类对象：
       类对象，就是类，也即类名
       python解释器在执行代码的过程中创建
       作用：
          使用类对象创建实例   - 类名()
          有自己的内存空间，可以保存一些属性值信息（类属性）
              类属性：
                定义：在类内部，方法外部，直接定义的变量，就是类属性
                使用：Person.name
                内存：只有类对象中存在一份
                例子：所有的狗尾巴不见了，且以后都不会再有尾巴，成为狗的物种特征，为类属性
          一个代码中，一个类只有一份内存空间
27、方法的划分：
    ① 实例方法（最常用）
          在类中直接定义：
              class Dog:
                  def func(self):        - 参数一般写作 self，表示实例对象
          什么时候用：如果方法中需要使用实例属性（使用 self），必须定义为实例方法
          调用：对象.方法名()   -不需要给 self 传参
    ② 类方法（会用）
          在方法名上方书写 @classmethod 装饰器（使用@classmethod装饰的方法）
              class Dog:
                 @classmethod
                 def func(cls):          - 参数一般写作cls，表示类对象（类名）  cls=class
          什么时候用：前提，方法中不需要使用实例属性（self）
                    用到了类属性，可以定义为类方法（也可以定义为实例方法）
          调用：类名.方法名()   -不需要给 cls 传参，python解释器自动传递
               实例.方法名()   -不需要给 cls 传参，python解释器自动传递
    ③ 静态方法（基本不用）
          在方法名上方书写 @staticmethod 装饰器（使用@staticmethod装饰的方法）
              class Dog:
                 @staticmethod
                 def func():          - 参数没有参数
          什么时候用：前提，方法中不需要使用实例属性（self）
                    也不使用类属性，可以定义为静态方法
          调用：类名.方法名()
               实例.方法名()
28、补充：
      哈希（hash）：是一个算法，可以对数据产生一个唯一的值（指纹）
      is：可以判断两个对象是否为同一对象，即，两个对象的引用地址是否一致     （了解 is 的含义即可）
          a is b 等价于 id(a) == id(b)
'''